import {mergeOptions} from "../util/options";
import {extend} from "../../shared/util";
import {ASSET_TYPES} from "../../shared/constants";

export function initExtend (Reactive) {

    Reactive.cid = 0;
    let cid = 1;

    /**
     * extend 类继承函数
     * 这里的 this 一般指向 Reactive, 入口是 initAssetsRegister
     * 由 Reactive 调用
     * @param {Object} extendOptions
     * @return {Function}
     */
    Reactive.extend = function (extendOptions) {
        // 防止 null 对象
        extendOptions = extendOptions || {};
        // 创建缓存， 父组件的 cid ==> 被构造的子组件构造函数
        const Super = this;
        const SuperId = Super.cid;
        const cacheCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
        if (cacheCtors[SuperId]) {
            return cacheCtors[SuperId];
        }

        const name = extendOptions.name || Super.options.name;
        // 检查名称是否合乎规范？

        // 创建子组件构造器
        const Sub = function ReactiveComponent (options) {
            this._init(options);
        }
        Sub.prototype = Object.create(Super.prototype);
        Sub.prototype.constructor = Sub;
        Sub.cid = cid ++;
        Sub.options = mergeOptions(Super.options, extendOptions);
        Sub['super'] = Super;

        // 属性继承
        // todo props的初始化

        // 公用方法继承
        Sub.extend = Super.extend;
        Sub.mixin = Super.mixin;

        // 继承资源
        ASSET_TYPES.forEach(type => {
            Sub[type+'s'] = Super[type+'s'];
        })
        // todo 这个功能有什么用？ 允许查看自己的定义？
        // if (name) {
        //     Sub.options.components[name] = Sub;
        // }

        // 保留组件类的配置信息
        Sub.superOptions = Super.options;
        Sub.extendOptions = extendOptions;
        Sub.sealedOptions = extend({}, Sub.options);

        // 缓存创建好的组件类构造器
        cacheCtors[SuperId] = Sub;
        return Sub;
    };
}
